package com.geekjob1120.geekjob1120pay.service;

import com.geekjob1120.geekjob1120pay.modle.Pay;
import com.geekjob1120.geekjob1120pay.modle.PayState;
import com.geekjob1120.geekjob1120pay.repository.PayRepository;
import com.geekjob1120.geekjob1120pay.util.SpringBeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.Session;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.PessimisticLockingFailureException;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.sql.DataSource;
import java.sql.SQLTimeoutException;

@Slf4j
public abstract class PayService {

    @Autowired
    PayRepository payRepository;
    @Value("${spring.datasource.url:nonono}")
    String jdbcUrl;
    public boolean payService(Pay pay){
        Pay result;
        PayService payService = (PayService) AopContext.currentProxy();
        try {
            pay.setState(PayState.INIT);
            result = payService.savePay(pay);
        }catch (DataIntegrityViolationException ex){
            log.info("订单 orderID={} 已存在，状态={}",pay.getOrderId(),pay.getState());
            result = payRepository.findByOrderId(pay.getOrderId());
            if(!PayState.INIT.equals(result.getState())){
                BeanUtils.copyProperties(result,pay);
                return false;
            }
        }
        return payService.lockAndPay(result,pay);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public boolean lockAndPay(Pay result,Pay pay) {
        try {
            result = payRepository.forupdate(result.getId());
        }
        catch (SQLTimeoutException sqlTimeoutException){
            log.info("订单{}处理中,SQlTimeou",result.getId());
            BeanUtils.copyProperties(result,pay);
            return false;
        }
        catch (PessimisticLockingFailureException pessimisticLockingFailureException){
            log.info("订单{}处理中,lockfail",result.getId());
            BeanUtils.copyProperties(result,pay);
            return false;
        }

        try {
            Thread.sleep(10000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        BeanUtils.copyProperties(result,pay);
        if(PayState.INIT.compareTo(result.getState()) != 0){
            return false;
        }
        if(pay(result)){
            result.setState(PayState.PAYED);
            payRepository.save(result);
            pay.setState(result.getState());
            return true;
        }else {
            result.setState(PayState.INIT);
            payRepository.save(result);
            pay.setState(result.getState());
            return false;
        }
    }

    abstract protected boolean pay(Pay pay);

    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Pay savePay(Pay pay)throws DuplicateKeyException{
        return payRepository.save(pay);
    }
}
